// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.warehouse.viewers.wizards;

import static org.dengues.core.IDesignerCoreService.ENCODING;
import static org.dengues.core.IDesignerCoreService.FILENAME;
import static org.dengues.core.IDesignerCoreService.LOOP_QUERY;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dengues.commons.utils.FileUtils;
import org.dengues.commons.utils.StringUtils;
import org.dengues.core.IDesignerCoreService;
import org.dengues.core.components.IXMLComponent;
import org.dengues.core.metadata.MetadataHelper;
import org.dengues.core.metadata.MetadataTable;
import org.dengues.core.metadata.types.DenguesTypesManager;
import org.dengues.core.metadata.types.JavaDataTypeHelper;
import org.dengues.core.metadata.types.MetadataTypesManager;
import org.dengues.core.warehouse.ENodeCategoryName;
import org.dengues.core.warehouse.ENodeStatus;
import org.dengues.designer.ui.DesignerUIPlugin;
import org.dengues.model.DenguesModelManager;
import org.dengues.model.database.DBColumn;
import org.dengues.model.database.DBTable;
import org.dengues.model.database.DatabaseDiagram;
import org.dengues.ui.metadata.MetadataTableViewer;
import org.dengues.warehouse.i18n.Messages;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf 2007-11-27 qiang.zhang $
 * 
 */
public abstract class NewElementWizardPage3 extends AbstractStorageWizardPage {

    protected static final String QUERY = "QUERY"; //$NON-NLS-1$

    protected static final String DEFAULT_LABEL = "Column"; //$NON-NLS-1$

    protected static final String COLUMN_NAME = IXMLComponent.COLUMN_SCHEMA;

    protected static final String RELATIVE_XPATH = "RELATIVE_XPATH"; //$NON-NLS-1$

    protected static final String ROOT_XPATH = LOOP_QUERY;

    protected IStatus nameStatus;

    protected DatabaseDiagram database;

    protected IPath path;

    protected DBTable dbtable;

    protected String fileName;

    protected Button guessBtn;

    protected MetadataTableViewer metadataViewer;

    private ENodeCategoryName name;

    protected Text enCodingtext;

    /**
     * Qiang.Zhang.Adolf@gmail.com NewDatabaseWizardPage constructor comment.
     * 
     * @param database
     * @param isActived
     */
    public NewElementWizardPage3(IPath path, DatabaseDiagram database, ENodeCategoryName name) {
        super(""); //$NON-NLS-1$
        nameStatus = createOkStatus();
        dbtable = DenguesModelManager.getDatabaseFactory().createDBTable();
        dbtable.setX(32);
        dbtable.setY(32);
        dbtable.setName(MetadataHelper.generateNewTableName(database, name.getName()));
        this.database = database;
        this.path = path;
        this.name = name;
        if (database != null) {
            fileName = ((String) database.getProperties().get(IDesignerCoreService.FILENAME));
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent) {
        GridLayout layout = new GridLayout();
        GridData gridData = new GridData(GridData.FILL_BOTH);
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        Composite container = new Composite(parent, SWT.NONE);
        layout = new GridLayout();
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        container.setLayout(layout);
        gridData = new GridData(GridData.FILL_BOTH);
        container.setLayoutData(gridData);

        Composite composite = new Composite(container, SWT.NONE);
        composite.setLayout(new GridLayout(2, false));
        composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        Label label = new Label(composite, SWT.NONE);
        label.setText(Messages.getString("NewCSVWizardPage3.encoding")); //$NON-NLS-1$
        enCodingtext = new Text(composite, SWT.BORDER);
        gridData = new GridData();
        gridData.widthHint = 120;
        enCodingtext.setLayoutData(gridData);
        if (database != null && database.getProperties().get(ENCODING) != null) {
            enCodingtext.setText((String) database.getProperties().get(ENCODING));
        } else {
            enCodingtext.setText("UTF-8");
        }
        createMiddleContent(container);

        composite = new Composite(container, SWT.NONE);
        layout = new GridLayout(3, false);
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        gridData = new GridData(GridData.FILL_HORIZONTAL);
        composite.setLayout(layout);
        composite.setLayoutData(gridData);
        label = new Label(composite, SWT.NONE);
        label.setText(Messages.getString("NewElementWizardPage3.tName")); //$NON-NLS-1$
        final Text text = new Text(composite, SWT.BORDER);
        text.setText(dbtable.getName());
        gridData = new GridData(GridData.FILL_HORIZONTAL);
        text.setLayoutData(gridData);
        text.addModifyListener(new ModifyListener() {

            /*
             * (non-Javadoc)
             * 
             * @see org.eclipse.swt.events.ModifyListener#modifyText(org.eclipse.swt.events.ModifyEvent)
             */
            public void modifyText(ModifyEvent e) {
                dbtable.setName(text.getText());
                metadataViewer.setTitle(dbtable.getName());
            }

        });
        guessBtn = new Button(composite, SWT.PUSH);
        guessBtn.setText(Messages.getString("NewElementWizardPage3.guessBtn")); //$NON-NLS-1$

        MetadataTable metadataTable = new MetadataTable();
        metadataViewer = new MetadataTableViewer(container, metadataTable);
        metadataViewer.initTableInput();
        metadataViewer.setTitle(dbtable.getName());
        setControl(container);
        setPageComplete(false);
        checkFieldsValue();
        addListeners();
    }

    protected abstract void addListeners();

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "createMiddleContent".
     * 
     * @param container
     */
    protected abstract void createMiddleContent(Composite container);

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "checkFieldsValue".
     */
    private void checkFieldsValue() {
        setMessage(nameStatus);
        boolean b = nameStatus.getSeverity() != IStatus.ERROR;
        setPageComplete(b);
    }

    public String getDatabaseStatus() {
        return ENodeStatus.NORMAL.getId();
    }

    private void setMessage(IStatus status) {
        if (IStatus.ERROR == status.getSeverity()) {
            setErrorMessage(status.getMessage());
            setMessage(""); //$NON-NLS-1$
        } else {
            setMessage(status.getMessage());
            setErrorMessage(null);
        }
    }

    private static IStatus createOkStatus() {
        return new Status(IStatus.OK, DesignerUIPlugin.PLUGIN_ID, IStatus.OK, "", null); //$NON-NLS-1$
    }

    /**
     * Getter for xmlFile.
     * 
     * @return the xmlFile
     */
    public String getFileName() {
        return this.fileName;
    }

    /**
     * Getter for dbtable.
     * 
     * @return the dbtable
     */
    public DBTable getDbtable() {
        return this.dbtable;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getProperties".
     * 
     * @return
     */
    public HashMap<String, Object> getProperties() {
        HashMap<String, Object> properties = new HashMap<String, Object>();
        properties.put(FILENAME, FileUtils.getPortablePath(getFileName()));
        properties.put(ENCODING, enCodingtext.getText());
        return properties;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "setFileName".
     * 
     * @param fileName
     */
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "retieveSchema".
     * 
     * @param csvRows
     * @param numberOfCol
     * @param firstRowToExtractMetadata
     * @param label
     */
    protected void retieveSchema(List<String[]> csvRows, List<Map<String, Object>> mappings) {
        dbtable.getColumns().clear();
        int i;
        if (csvRows.size() > 0) {
            String[] fields = csvRows.get(0);
            int numberOfCol = fields.length;

            // define the label to the metadata width the content of the first row
            int firstRowToExtractMetadata = 0;

            // the first rows is used to define the label of any metadata
            String[] label = new String[numberOfCol];
            for (i = 0; i < numberOfCol; i++) {
                label[i] = DEFAULT_LABEL + i; //$NON-NLS-1$
                if (firstRowToExtractMetadata == 0) {
                    if (mappings != null && mappings.size() > i && mappings.get(i).get(QUERY) != null
                            && !mappings.get(i).get(QUERY).equals("")) { //$NON-NLS-1$
                        label[i] = "" + ((String) mappings.get(i).get(QUERY)).trim().replaceAll(" ", "_"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                        label[i] = StringUtils.validateColumnNameFormat(label[i], i);
                    }
                }
            }
            for (i = 0; i < numberOfCol; i++) {
                // define the first currentType and assimile it to globalType
                String globalType = null;
                int lengthValue = 0;
                int precisionValue = 0;

                int current = firstRowToExtractMetadata;
                while (globalType == null) {
                    if (i >= csvRows.get(current).length) {
                        globalType = "id_String"; //$NON-NLS-1$
                    } else {
                        globalType = JavaDataTypeHelper.getDenguesTypeOfValue(csvRows.get(current)[i]);
                        current++;
                        // if (current == csvRows.size()) {
                        // globalType = "id_String"; //$NON-NLS-1$
                        // }
                    }
                }
                // for another lines
                for (int f = firstRowToExtractMetadata; f < csvRows.size(); f++) {
                    fields = csvRows.get(f);
                    if (fields.length > i) {
                        String value = fields[i];
                        if (!value.equals("")) { //$NON-NLS-1$

                            if (!JavaDataTypeHelper.getDenguesTypeOfValue(value).equals(globalType)) {
                                globalType = JavaDataTypeHelper.getCommonType(globalType, JavaDataTypeHelper
                                        .getDenguesTypeOfValue(value));
                            }
                            if (lengthValue < value.length()) {
                                lengthValue = value.length();
                            }
                            int positionDecimal = 0;
                            if (value.indexOf(',') > -1) {
                                positionDecimal = value.lastIndexOf(',');
                                precisionValue = lengthValue - positionDecimal;
                            } else if (value.indexOf('.') > -1) {
                                positionDecimal = value.lastIndexOf('.');
                                precisionValue = lengthValue - positionDecimal;
                            }
                        }
                    }
                }

                // define the metadataColumn to field i
                DBColumn metadataColumn = DenguesModelManager.getDatabaseFactory().createDBColumn();
                // Convert javaType to DataType
                String dataType = null;
                dataType = globalType;
                if (globalType.equals(DenguesTypesManager.FLOAT.getId()) || globalType.equals(DenguesTypesManager.DOUBLE.getId())) {
                    metadataColumn.setPrecision(precisionValue);
                } else {
                    metadataColumn.setPrecision(0);
                }
                metadataColumn.setType(MetadataTypesManager.getDBTypeFromJavaType(dataType));
                metadataColumn.setLength(lengthValue);

                // Check the label and add it to the table
                metadataColumn.setName(MetadataHelper.generateNewColumnName(dbtable, label[i]));
                dbtable.getColumns().add(i, metadataColumn);
                metadataViewer.refreshMetadataTable(MetadataHelper.convertMetadataTable(dbtable));
            }
        }
    }

}
